package com.gopay.checkorder.service.impl;

import com.gopay.checkorder.manager.BankOrderManager;
import com.gopay.checkorder.service.BankOrderService;
import com.gopay.checkorder.service.task.BankCountDownLatch;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.bank.NuccConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.dayend.BaseDayendEntry;
import com.gopay.common.domain.bank.nucc.common.query.res.NuccQueryRes;
import com.gopay.common.domain.cashier.BankCardType;
import com.gopay.common.domain.cps.vo.CheckOrderResult;
import com.gopay.common.domain.cps.vo.InAccInfo;
import com.gopay.remote.bank.BankInteractRemoteService;
import java.math.BigDecimal;
import java.util.List;
import javax.annotation.Resource;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @CheckOrderNuccB2bImpl.java
 * @author zhoutong
 * @2018-1-17 下午4:44:15 www.gopay.com.cn Inc.All rights reserved.
 */
public class CheckOrderNuccB2bImpl implements BankOrderService {

	private final static Logger logger = LoggerFactory.getLogger("NUCCPAY");

	@Resource(name = "bankClient")
	private BankInteractRemoteService bankClient;
	@Resource(name = "bankOrderManager")
	protected BankOrderManager bankOrderManager;
	@Override
	public CheckOrderResult checkOrder(BankOrder bankOrder, String target) {
		CheckOrderResult checkOrderResult = new CheckOrderResult();
		checkOrderResult.setSuccess(false);
		checkOrderResult.setOrderId(bankOrder.getOrderId());
		try {
			BaseMessage base = new BaseMessage();
			base.setOrderId(bankOrder.getOrderId());
			base.setBankOrderId(bankOrder.getOutOrderId());
			base.setBank(bankOrder.getBankCode());
			base.setBankIntrChann(BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()));
			base.setBankBusProd(BisBankBusinessProd.get(bankOrder.getBankBizProdCode()));
			Result result;
			result = bankClient.query(base);
			if (result == null || !result.isSuccess()) {
				logger.debug("bankClient fail.");				
				if(result ==null || ProcCodeConstants.PROC_CODE_100E6036.equals(result.getResultCode())){
					BankCountDownLatch.failIncrease(bankOrder.getBankCode());
					checkOrderResult.setCommunicateError(true);
	            }				
				logger.debug(ToStringBuilder.reflectionToString(result,ToStringStyle.DEFAULT_STYLE));
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
				checkOrderResult.setErrMsg("系统返回对账结果为空");
				return checkOrderResult;
			}
			NuccQueryRes res = (NuccQueryRes) result.getDefaultModel();
			if (res == null) {
				// 查询订单为空
				logger.error("网联B2B对账失败，返回为null，orderId："+ bankOrder.getOrderId() + " errcode:"+ ProcCodeConstants.PROC_CODE_100E5062+ " err:bis query is null.");
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5062);
				checkOrderResult.setErrMsg("银行返回对账结果为空");
			}
			String sysRtnCd = res.getMsgBody().getSysRtnInf().getSysRtnCd(); //该笔订单查询交易的状态
			String sysRtnDesc = res.getMsgBody().getSysRtnInf().getSysRtnDesc(); //该笔订单查询交易的状态描述
			if (!NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(sysRtnCd)) {
				// 查询订单错误
				logger.error("网联网关B2B查询订单 = "+ bankOrder.getOrderId() + "失败.查询交易系统返回码:"+ sysRtnCd + "查询交易描述：" + sysRtnDesc);
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5062);
				checkOrderResult.setErrMsg(sysRtnDesc);
				return checkOrderResult;
			}
			String  oriSysRtnCd = res.getMsgBody().getBizInf().getOriSysRtnCd();//原系统返回码
			String  oriSysRtnDesc = res.getMsgBody().getBizInf().getOriSysRtnDesc();//原系统返回码说明
			String  oriBizStsCd = res.getMsgBody().getBizInf().getOriBizStsCd();//原业务返回码
			String  oriBizStsDesc = res.getMsgBody().getBizInf().getOriBizStsDesc();//原业务返回码说明
			String  oriTrxStatus = res.getMsgBody().getBizInf().getOriTrxStatus();//原交易状态
			String  oriTrxId = res.getMsgBody().getBizInf().getOriTrxId();//原交易流水号
			String  oriTrxAmt = res.getMsgBody().getBizInf().getOriTrxAmt();//原交易金额
			if (!StringUtils.isBlank(oriTrxStatus)) {
				// 成功
				if (oriTrxStatus.equals(NuccConstants.NUCC_TRXSTATUSCD_SUCCESS)
						|| oriTrxStatus.equals(NuccConstants.NUCC_EXCEPTION_SUCCESS)) {
					logger.info("网联B2B订单:" + oriTrxId + "交易成功("+ oriTrxStatus + ")");
					checkOrderResult.setSuccess(true);
					InAccInfo accInfo = new InAccInfo();
					accInfo.setOrderId(bankOrder.getOrderId());
					accInfo.setAmount(new BigDecimal(oriTrxAmt.substring(3)));
					accInfo.setRetCode("00");
					accInfo.setCardType(BankCardType.Unknown.toString());
					checkOrderResult.setAccInfo(accInfo);
					// 交易成功，需获取银行返回的付款行银行流水号，退款时使用
					bankOrder.setBankOrderId(res.getMsgBody().getBizInf().getDbtrBankId());
					bankOrderManager.update(bankOrder);
				}
				// 处理中
				else if (oriTrxStatus.equals(NuccConstants.NUCC_TRXSTATUSCD_PROCESSING)) {
					logger.info("网联B2B订单:" + oriTrxId+ "订单状态为：处理中，有待后续继续查询(" + oriTrxStatus + ")");
					checkOrderResult.setErrMsg("银行返回交易未确认");
				}
				// 交易失败
				else if (oriTrxStatus.equals(NuccConstants.NUCC_TRXSTATUSCD_FAIL)
						|| oriTrxStatus.equals(NuccConstants.NUCC_EXCEPTION_FAIL)) {
					checkOrderResult.setBankFailure(true);
					logger.info("网联B2B订单:" + oriTrxId + "交易失败("+ oriTrxStatus + ")系统返回("+oriSysRtnCd+oriSysRtnDesc+")业务返回("+oriBizStsCd + oriBizStsDesc+")");
					checkOrderResult.setErrMsg("银行返回交易失败("+ oriTrxStatus + ")系统返回("+oriSysRtnCd+oriSysRtnDesc+")业务返回("+oriBizStsCd + oriBizStsDesc+")");
				}
				// 未知
				else {
					logger.info("网联B2B订单:" + oriTrxId+ "订单状态为：未知，有待后续继续查询(" + oriTrxStatus + ")");
					checkOrderResult.setErrMsg("银行返回交易未知");
				}
			}
			return checkOrderResult;
		} catch (Exception e) {
			logger.error("bankClient fail.", e);
			checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
			checkOrderResult.setErrMsg("对账调用bis失败");
			return checkOrderResult;
		}
	}

	@Override
	public BankOrder getDbOrder() {
		return null;
	}

	@Override
	public BaseMessage dayend(String bank_bus) {
		return null;
	}

	@Override
	public Result getDayendMsg(String string) {
		return null;
	}

	@Override
	public List<CheckOrderResult> checkDayend(String bank_bus) {
		return null;
	}

	@Override
	public CheckOrderResult checkDayendOrder(BaseDayendEntry bdm, BankOrder bo) {
		return null;
	}
}
